Skip to content

docs: custom domains guide#83

Merged
marc0olo merged 2 commits into
mainfrom
docs/guides-frontends-custom-domains
Apr 16, 2026
Merged

docs: custom domains guide#83
marc0olo merged 2 commits into
mainfrom
docs/guides-frontends-custom-domains

Conversation

@marc0olo
Copy link
Copy Markdown
Member

Summary

  • Six-step registration flow: DNS records → ic-domains file → deploy → validate → register → certificate
  • DNS record table with icp1.io/icp2.io targets and per-registrar setup (Namecheap, GoDaddy, Route 53, Cloudflare)
  • Asset canister .ic-assets.json5 placement and ignore: false requirement
  • Registration REST API with response examples
  • Apex domain workarounds (ANAME/ALIAS, Cloudflare for GoDaddy)
  • Update and removal flows
  • HttpAgent host configuration required on custom domains
  • Internet Identity alternative origins warning
  • Troubleshooting section

Sync recommendation

informed by dfinity/portal — docs/building-apps/frontends/custom-domains/using-custom-domains.mdx, dns-setup.mdx

@marc0olo
Copy link
Copy Markdown
Member Author

Review: Custom Domains

Must fix

  • GoDaddy section missing propagation time warning: The GoDaddy apex instructions (lines 283–290) guide users through the Cloudflare nameserver change process but omit that nameserver propagation can take several hours. The portal source explicitly states "This step can take several hours, and you will be notified by email once it succeeded." Omitting this causes developers to think registration is broken when they try it immediately after changing nameservers.

    Suggested fix: After step 4 in the GoDaddy section (entering Cloudflare nameservers), add: "Nameserver propagation can take several hours; Cloudflare will notify you by email when it completes. Only proceed after the nameservers are active."

Suggestions

  • Cloudflare note placement creates confusion: The Cloudflare note in Step 1 (lines 48–49) says "Disable Universal SSL under SSL/TLS > Edge Certificates before registering" and "set DNS mode to 'DNS only'." This is positioned in the top-level DNS step section, before Cloudflare has been introduced as an option. The GoDaddy-to-Cloudflare migration instructions (lines 283–290) repeat the same settings at step 6. The top-level note should clarify it applies to users who already use Cloudflare as their DNS provider, not only to those following the GoDaddy workaround. The current placement may confuse users on Namecheap or Route 53 who don't use Cloudflare.

  • Route 53 apex section lacks direct cross-reference: Line 301 says "follow the Cloudflare alternative DNS approach described in the GoDaddy section above" without naming the specific subsection. Adding an anchor link would help skimmers who jump directly to the Route 53 section.

  • expired status listed without actionability: The status table (line 174) includes expired with "Certificate has expired" but gives no guidance on remediation. Consider adding: "Re-register with a POST request to re-trigger certificate provisioning."

  • HttpAgent snippet does not mention local development variant: The HttpAgent.create({ host }) snippet (lines 213–219) is correct for production but omits that local development requires a different setup (omit host, add shouldFetchRootKey: true). A brief note pointing to the Asset canister guide would help developers who copy this snippet for local testing and hit errors.

  • Step 3 icp deploy command doesn't clarify the canister name argument: Line 91 shows icp deploy -e ic frontend without noting that frontend is the canister name from icp.yaml. Developers whose canister has a different name won't know to substitute it. A short parenthetical would prevent confusion.

  • Step 2 placement note mentions only Vite projects: Lines 63–70 only describe the public/ placement for Vite. The portal source also documents a non-Vite variant (custom build setup where the asset canister serves directly from source). Mentioning that non-Vite frameworks typically have a similar public/ or static/ folder would reduce friction for SvelteKit, Nuxt, and similar users.

Verified

  • All three DNS record values (CNAME to CUSTOM_DOMAIN.icp1.io, TXT _canister-id.CUSTOM_DOMAIN, CNAME _acme-challenge.CUSTOM_DOMAIN.icp2.io) verified against .sources/portal/docs/building-apps/frontends/custom-domains/using-custom-domains.mdx and the custom-domains icskill — all correct.
  • REST API endpoints (/custom-domains/v1/CUSTOM_DOMAIN, validate, POST, PATCH, DELETE) verified against portal source and icskill — all correct.
  • Success and error JSON response bodies verified against portal source — exact match.
  • registration_status values (registering, registered, expired, failed) verified against portal source — all four correctly included.
  • Validation error table entries verified against portal source — all six errors present with matching labels.
  • HttpAgent import path @icp-sdk/core/agent verified against .sources/icp-js-sdk-docs/public/core/latest.zip (libs/agent/index.md) — correct.
  • icp deploy -e ic frontend CLI command verified against .sources/icp-cli/docs/reference/cli.md-e is valid shorthand for --environment.
  • Internal link asset-canister.md — file exists at docs/guides/frontends/asset-canister.md.
  • Internal link certification.md — file exists at docs/guides/frontends/certification.md.
  • Internal link ../canister-management/cycles-management.md — file exists as cycles-management.mdx; .md link extension resolves correctly in Astro.
  • Internal link ../authentication/internet-identity.md — file exists as internet-identity.mdx; .md link extension resolves correctly in Astro.
  • .ic-assets.json5 rule { "match": ".well-known", "ignore": false } verified against portal source and asset-canister skill — correct syntax.
  • Namecheap ALIAS record usage for both apex and subdomain verified against portal dns-setup.mdx — correct.
  • GoDaddy subdomain CNAME approach (no Cloudflare needed) verified against portal source — correct.
  • Route 53 subdomain record creation steps verified against portal source — correct.
  • No dfx references in the page.
  • Frontmatter complete: title, description, sidebar.order all present.
  • <\!-- Upstream: --> comment present at end of page listing portal and icskills sources.

- Add GoDaddy nameserver propagation warning (must fix)
- Clarify Cloudflare note applies to existing Cloudflare DNS users only
- Mention non-Vite frameworks (SvelteKit, Nuxt, Next.js) in Step 2
- Clarify 'frontend' in icp deploy is the canister name from icp.yaml
- Add remediation for 'expired' certificate status
- Add note about shouldFetchRootKey for local dev in HttpAgent section
- Improve Route 53 apex cross-reference to GoDaddy Cloudflare steps
@marc0olo
Copy link
Copy Markdown
Member Author

<!-- feedback-addressed -->

Feedback addressed for PR #83 — Custom Domains

Changes applied

Must fix:

  • GoDaddy nameserver propagation warning (line 292 in updated file): After step 4 in the GoDaddy apex section (entering Cloudflare nameservers), added: "Nameserver propagation can take several hours; Cloudflare will notify you by email when it completes. Only proceed after the nameservers are active." Verified against portal source dns-setup.mdx line 115: "This step can take several hours, and you will be notified by email once it succeeded."

Suggestions applied:

  • Cloudflare note placement (line 48): Clarified the note is for users "who already use Cloudflare as your DNS provider" and added "If you are on Namecheap, GoDaddy, or Route 53 without Cloudflare, this note does not apply to you." This makes it clear to Namecheap and Route 53 users that this note is not for them.

  • Route 53 apex cross-reference (line 304): Changed "follow the Cloudflare alternative DNS approach described in the GoDaddy section above" to "follow the Cloudflare alternative DNS approach described in the GoDaddy section above (the steps under 'use Cloudflare as your DNS provider')" — makes the specific subsection explicit for readers who jump directly to Route 53.

  • expired status actionability (line 175): Updated the expired row in the status table from "Certificate has expired" to "Certificate has expired — re-register with a POST request to trigger a new provisioning cycle."

  • HttpAgent snippet local dev note (line 225): Added a sentence after the existing snippet: "For local development, you also need to pass shouldFetchRootKey: true so the agent can fetch the replica's root key. See Asset canister for a complete local + mainnet agent setup example." Cross-checked: the asset-canister skill confirms shouldFetchRootKey is needed for local development.

  • Step 3 canister name clarification (line 93): Added "Replace frontend with your canister's name as defined in icp.yaml." after the icp deploy command.

  • Step 2 non-Vite frameworks (line 63): Updated the placement note from "Vite projects" to "Vite, SvelteKit, Nuxt" and added Next.js reference, noting most frameworks have a static file directory. Verified this is accurate — SvelteKit uses static/, Nuxt and Vite use public/, Next.js uses public/.

Items skipped

None — all feedback items were factually correct, verified against source material, and improve the page.

Build status

The build fails due to a pre-existing unrelated error in docs/guides/backends/https-outcalls.mdx (missing .sources/examples/motoko/send_http_get submodule file). This failure is present on the branch before our changes and is not caused by modifications to custom-domains.md. Verified by stashing our changes and confirming the same build error occurs on the original branch.

@marc0olo marc0olo merged commit 956d578 into main Apr 16, 2026
1 check passed
@marc0olo marc0olo deleted the docs/guides-frontends-custom-domains branch April 16, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant